}
}
+static void flush_cache_for_context_switch(struct vcpu *next)
+{
+ extern cpumask_t cpu_cache_coherent_map;
+ int cpu = smp_processor_id();
+
+ if (is_idle_vcpu(next) ||
+ __test_and_clear_bit(cpu, &next->arch.cache_coherent_map)) {
+ if (cpu_test_and_clear(cpu, cpu_cache_coherent_map)) {
+ unsigned long flags;
+ u64 progress = 0;
+ s64 status;
+
+ local_irq_save(flags);
+ status = ia64_pal_cache_flush(4, 0, &progress, NULL);
+ local_irq_restore(flags);
+ if (status != 0)
+ panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
+ "cache_type=4 status %lx", status);
+ }
+ }
+}
+
static void lazy_fp_switch(struct vcpu *prev, struct vcpu *next)
{
/*
}
flush_vtlb_for_context_switch(prev, current);
+ flush_cache_for_context_switch(current);
context_saved(prev);
}
return ((struct sal_ret_values) {status, r9, r10, r11});
}
+cpumask_t cpu_cache_coherent_map;
+
+struct cache_flush_args {
+ u64 cache_type;
+ u64 operation;
+ u64 progress;
+ long status;
+};
+
+static void
+remote_pal_cache_flush(void *v)
+{
+ struct cache_flush_args *args = v;
+ long status;
+ u64 progress = args->progress;
+
+ status = ia64_pal_cache_flush(args->cache_type, args->operation,
+ &progress, NULL);
+ if (status != 0)
+ args->status = status;
+}
+
struct ia64_pal_retval
xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3)
{
status = ia64_pal_register_info(in1, &r9, &r10);
break;
case PAL_CACHE_FLUSH:
+ if (in3 != 0) /* Initially progress_indicator must be 0 */
+ panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
+ "progress_indicator=%lx", in3);
+
/* Always call Host Pal in int=0 */
in2 &= ~PAL_CACHE_FLUSH_CHK_INTRS;
+ if (in1 != PAL_CACHE_TYPE_COHERENT) {
+ struct cache_flush_args args = {
+ .cache_type = in1,
+ .operation = in2,
+ .progress = 0,
+ .status = 0
+ };
+ smp_call_function(remote_pal_cache_flush,
+ (void *)&args, 1, 1);
+ if (args.status != 0)
+ panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
+ "remote status %lx", args.status);
+ }
+
/*
* Call Host PAL cache flush
* Clear psr.ic when call PAL_CACHE_FLUSH
panic_domain(NULL, "PAL_CACHE_FLUSH ERROR, "
"status %lx", status);
+ if (in1 == PAL_CACHE_TYPE_COHERENT) {
+ int cpu = current->processor;
+ cpus_setall(current->arch.cache_coherent_map);
+ cpu_clear(cpu, current->arch.cache_coherent_map);
+ cpus_setall(cpu_cache_coherent_map);
+ cpu_clear(cpu, cpu_cache_coherent_map);
+ }
break;
case PAL_PERF_MON_INFO:
{